package com.cy.hui_jie_dan.service.impl;


import com.cy.hui_jie_dan.comon.constant.JwtClaimsConstant;
import com.cy.hui_jie_dan.comon.constant.passwordconstan;
import com.cy.hui_jie_dan.comon.constant.captchaConstant;
import com.cy.hui_jie_dan.comon.constant.phonePassConstant;
import com.cy.hui_jie_dan.comon.context.BaseContext;
import com.cy.hui_jie_dan.comon.exception.PassWordExceptio;
import com.cy.hui_jie_dan.comon.exception.captchaException;
import com.cy.hui_jie_dan.comon.exception.phonePassException;
import com.cy.hui_jie_dan.comon.properties.JwtProperties;
import com.cy.hui_jie_dan.comon.utils.JwtUtil;
import com.cy.hui_jie_dan.comon.utils.SecureCaptchaGenerator;

import com.cy.hui_jie_dan.mapper.UserMapper;
import com.cy.hui_jie_dan.popj.dto.userLoginDTO;
import com.cy.hui_jie_dan.popj.entity.User;
import com.cy.hui_jie_dan.service.userService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.Date;
import io.jsonwebtoken.Claims;

@Service
public class userServiceImpl implements userService {
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    @Autowired
    UserMapper userMapper;
    @Autowired
    JwtProperties jwtProperties;
    @Override
    public String generate(userLoginDTO userLoginDTO) {
        String s = SecureCaptchaGenerator.generateCaptcha(6);
        String phoneNumber = userLoginDTO.getPhoneNumber();
        if (phoneNumber != null){
            if (redisTemplate.opsForValue().get(userLoginDTO.getPhoneNumber())==null){
                redisTemplate.opsForValue().set(userLoginDTO.getPhoneNumber(),s, 300, TimeUnit.SECONDS );
                return s;
            }else {
                return "验证码未过期";
            }
        }else {
            throw new phonePassException(phonePassConstant.SET_PHONE_PASS);
        }

    }

    @Override
    public boolean register(userLoginDTO userLoginDTO) {
        User user1 = userMapper.selectByPhone(userLoginDTO.getPhoneNumber());
        if (user1!=null){
            redisTemplate.delete(userLoginDTO.getPhoneNumber());
            throw new phonePassException(phonePassConstant.SET_PHONE_em);
        }
        Object captcha = redisTemplate.opsForValue().get(userLoginDTO.getPhoneNumber());
        String password = userLoginDTO.getPassword();
        if (captcha != null && !captcha.equals(userLoginDTO.getCaptcha())) {
            return false;
        }
        User user = new User();

        BeanUtils.copyProperties(userLoginDTO,user);
        if(password==null){
            return false;
        }
        user.setEditTime(LocalDateTime.now());
        String s = DigestUtils.md5DigestAsHex(password.getBytes());
        user.setPassword(s);
        int insert = userMapper.insert(user);
        if (insert==1){
            redisTemplate.delete(user.getPhoneNumber());
            return true;
        }
        return false;

    }

    @Override
    public String login(userLoginDTO userLoginDTO) {
        String password = userLoginDTO.getPassword();
        if (password==null){
            throw new PassWordExceptio(passwordconstan.SET_PASSWORD_PASS);
        }
        User user = userMapper.selectByPhone(userLoginDTO.getPhoneNumber());
        if (user == null) {
            throw new phonePassException(phonePassConstant.SET_PHONE_PASS);
        }
        String s = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!user.getPassword().equals(s)){
            throw  new PassWordExceptio(passwordconstan.SET_PASSWORD_E);
        }

        // 检查用户是否已在其他设备登录
        String redisKey = "user_token:" + user.getUserId();
        String existingToken = (String) redisTemplate.opsForValue().get(redisKey);
        
        // 如果存在旧token，先检查token是否有效
        if (existingToken != null) {
            try {
                Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), existingToken);
                if (claims != null && claims.getExpiration().after(new Date())) {
                    // Token仍然有效，说明用户确实在其他设备登录
                    throw new phonePassException("该账号已在其他设备登录，请先退出其他设备");
                }
            } catch (Exception e) {
                // Token无效，可以继续登录
                redisTemplate.delete(redisKey);
            }
        }

        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getUserId());
        String token = JwtUtil.createJWT(
                jwtProperties.getUserSecretKey(),
                jwtProperties.getUserTtl(),
                claims);

        // 将新token存入Redis，设置过期时间与JWT过期时间一致
        redisTemplate.opsForValue().set(
            redisKey,
            token,
            jwtProperties.getUserTtl(),
            TimeUnit.MILLISECONDS
        );

        return token;
    }

    @Override
    public boolean change(userLoginDTO userLoginDTO) {
        String o = (String)redisTemplate.opsForValue().get(userLoginDTO.getPhoneNumber());
        if (o == null || !o.equals(userLoginDTO.getCaptcha())) {
            throw new captchaException(captchaConstant.SET_CAPTCHA_EX);
        }
        User user = userMapper.selectByPhone(userLoginDTO.getPhoneNumber());
        if (user==null){
            throw new phonePassException(phonePassConstant.SET_PHONE_PASS);
        }
        String password = userLoginDTO.getNewPassword();
        if (password==null){
            throw new PassWordExceptio(passwordconstan.SET_PASSWORD_PASS);
        }
        String s = DigestUtils.md5DigestAsHex(password.getBytes());
        user.setPassword(s);
        int i = userMapper.updateByPrimaryKey(user);
        if (i!=1){
            return false;
        }
        redisTemplate.delete(userLoginDTO.getPhoneNumber());
        return true;
    }

    @Override
    public boolean updataByPassWord(userLoginDTO userLoginDTO) {
        String newPassword = userLoginDTO.getNewPassword();
        Long currentId = BaseContext.getCurrentId();
        if (currentId==null || newPassword==null){
            throw new PassWordExceptio(passwordconstan.SET_PASSWORD_PASS);
        }
        String s = DigestUtils.md5DigestAsHex(newPassword.getBytes());
        return userMapper.updataPassWord(currentId,s)==1;

    }

    @Override
    public List<Map<String, Object>> listOtherUsers(Integer myUserId) {
        List<User> users = userMapper.selectAllExceptMe(myUserId);
        List<Map<String, Object>> result = new ArrayList<>();
        for (User user : users) {
            Map<String, Object> map = new HashMap<>();
            map.put("userId", user.getUserId());
            map.put("name", user.getNickname());
            map.put("avatar", user.getAvatar());
            result.add(map);
        }
        return result;
    }

    @Override
    public User getUserByPhone(String phoneNumber) {
        return userMapper.selectByPhone(phoneNumber);
    }

    @Override
    public String getNicknameById(Integer id) {
        return userMapper.selectNicknameById(id);
    }

    // 添加登出方法
    @Override
    public void logout(Long userId) {
        // 删除Redis中的token
        redisTemplate.delete("user_token:" + userId);
    }
}
